import type { TouchEvent } from 'mxp-uni-types';
import mxpGetSysInfoStore from '../mxp-tool/store/mxp-store-sys-info';

type ClipStart = {
  width: number;
  height: number;
  x: number;
  y: number;
  clipY: number;
  clipX: number;
  corner: number;
};

export const getData = () => ({
  /** 画布的宽度 */
  canvasWidth: 0,
  /** 画布的高度 */
  canvasHeight: 0,
  /** 裁剪框的 X 坐标 */
  clipX: 0,
  /** 裁剪框的 Y 坐标 */
  clipY: 0,
  /** 裁剪框高度 */
  clipWidth: 0,
  /** 裁剪框宽度 */
  clipHeight: 0,
  animation: false,
  imageWidth: 0,
  imageHeight: 0,
  imageTop: 0,
  imageLeft: 0,
  scale: 1,
  angle: 0,
  image: '',
  imageInit: false,
  sysinfo: {} as UniApp.GetSystemInfoResult,
  throttleTimer: null as NodeJS.Timeout | null,
  throttleFlag: true,
  timeClipCenter: null as NodeJS.Timeout | null,
  flagClipTouch: false,
  flagEndTouch: false,
  clipStart: null as ClipStart | null,
  animationTimer: null as NodeJS.Timeout | null,
  touchRelative: [{ x: 0, y: 0 }],
  hypotenuseLength: 0,
  ctx: null as UniApp.CanvasContext | null,
  canvasId: 'mxp-clipper',
});

export type Data = ReturnType<typeof getData>;

/**
 * 判断手指触摸位置
 */
export function determineDirection(clipX: number, clipY: number, clipWidth: number, clipHeight: number, currentX: number, currentY: number) {
  let corner = 0;
  /**
   * 思路：（利用直角坐标系）
   * 1.找出裁剪框中心点
   * 2.如点击坐标在上方点与左方点区域内，则点击为左上角
   * 3.如点击坐标在下方点与右方点区域内，则点击为右下角
   * 4.其他角同理
   */
  const mainPoint: [number, number] = [clipX + clipWidth / 2, clipY + clipHeight / 2]; // 中心点
  const currentPoint: [number, number] = [currentX, currentY]; // 触摸点

  if (currentPoint[0] <= mainPoint[0] && currentPoint[1] <= mainPoint[1]) {
    corner = 3; // 左上
  } else if (currentPoint[0] >= mainPoint[0] && currentPoint[1] <= mainPoint[1]) {
    corner = 2; // 右上
  } else if (currentPoint[0] <= mainPoint[0] && currentPoint[1] >= mainPoint[1]) {
    corner = 4; // 左下
  } else if (currentPoint[0] >= mainPoint[0] && currentPoint[1] >= mainPoint[1]) {
    corner = 1; // 右下
  }

  return corner;
}

/**
 * 图片边缘检测检测时，计算图片偏移量
 */
export function calcImageOffset(data: Data, scale: number) {
  let left = data.imageLeft;
  let top = data.imageTop;
  // eslint-disable-next-line no-param-reassign
  scale = scale || data.scale;

  let imageWidth = data.imageWidth;
  let imageHeight = data.imageHeight;
  if ((data.angle / 90) % 2) {
    imageWidth = data.imageHeight;
    imageHeight = data.imageWidth;
  }
  const { clipX, clipWidth, clipY, clipHeight } = data;

  // 当前图片宽度/高度
  const currentImageSize = (size: number) => (size * scale) / 2;
  const currentImageWidth = currentImageSize(imageWidth);
  const currentImageHeight = currentImageSize(imageHeight);

  left = clipX + currentImageWidth >= left ? left : clipX + currentImageWidth;
  left = clipX + clipWidth - currentImageWidth <= left ? left : clipX + clipWidth - currentImageWidth;
  top = clipY + currentImageHeight >= top ? top : clipY + currentImageHeight;
  top = clipY + clipHeight - currentImageHeight <= top ? top : clipY + clipHeight - currentImageHeight;
  return { left, top, scale };
}

/**
 * 图片边缘检测时，计算图片缩放比例
 */
export function calcImageScale(
  data: { scale: number; imageWidth: number; imageHeight: number; clipWidth: number; clipHeight: number; angle: number },
  scale?: number
) {
  // eslint-disable-next-line no-param-reassign
  scale = scale || data.scale;
  let { imageWidth, imageHeight } = data;
  const { clipWidth, clipHeight, angle } = data;
  if ((angle / 90) % 2) {
    [imageWidth, imageHeight] = [imageHeight, imageWidth];
  }
  if (angle !== 0 && scale === Math.max(clipWidth / imageHeight, clipHeight / imageWidth)) {
    return Math.max(clipWidth / imageWidth, clipHeight / imageHeight);
  }
  if (imageWidth * scale < clipWidth) {
    // eslint-disable-next-line no-param-reassign
    scale = clipWidth / imageWidth;
  }
  if (imageHeight * scale < clipHeight) {
    // eslint-disable-next-line no-param-reassign
    scale = Math.max(scale, clipHeight / imageHeight);
  }
  return scale;
}

/**
 * 计算图片尺寸
 */
export function calcImageSize(width: number, height: number, data: Data, data2: { originWidth: number; originHeight: number }) {
  let imageWidth = width;
  let imageHeight = height;
  const { clipWidth, clipHeight, sysinfo } = data;
  const { originWidth, originHeight } = data2;
  const cw = clipWidth || originWidth;
  const ch = clipHeight || originHeight;
  if (imageWidth && imageHeight) {
    if (imageWidth / imageHeight > cw / ch) {
      imageHeight = clipHeight || originHeight;
      imageWidth = (width / height) * imageHeight;
    } else {
      imageWidth = cw;
      imageHeight = (height / width) * imageWidth;
    }
  } else {
    const sys = sysinfo || mxpGetSysInfoStore().getSysInfo().value;
    imageWidth = sys.windowWidth;
    imageHeight = 0;
  }
  return {
    imageWidth,
    imageHeight,
  };
}

/**
 * 勾股定理求斜边
 */
export function calcPythagoreanTheorem(width: number, height: number) {
  return Math.sqrt(width ** 2 + height ** 2);
}

/**
 * 拖动裁剪框时计算
 */
export function clipTouchMoveOfCalculate(
  data: Data,
  data2: { isLockRatio: boolean; maxWidth: number; minWidth: number; maxHeight: number; minHeight: number },
  event: TouchEvent
) {
  const clientX = event.touches[0]!.clientX!;
  const clientY = event.touches[0]!.clientY!;

  const { clipWidth, clipHeight, clipY: oldClipY, clipX: oldClipX, clipStart } = data;
  // eslint-disable-next-line prefer-const
  let { isLockRatio, maxWidth, minWidth, maxHeight, minHeight } = data2;
  maxWidth = uni.upx2px(maxWidth); // maxWidth / 2;
  minWidth = uni.upx2px(minWidth); // minWidth / 2;
  minHeight = uni.upx2px(minHeight); // minHeight / 2;
  maxHeight = uni.upx2px(maxHeight); // maxHeight / 2;

  let width = clipWidth;
  let height = clipHeight;
  let clipY = oldClipY;
  let clipX = oldClipX;
  // 获取裁剪框实际宽度/高度
  // 如果大于最大值则使用最大值
  // 如果小于最小值则使用最小值
  const sizecorrect = () => {
    width = width <= maxWidth ? (width >= minWidth ? width : minWidth) : maxWidth;
    height = height <= maxHeight ? (height >= minHeight ? height : minHeight) : maxHeight;
  };
  const sizeinspect = () => {
    if ((width > maxWidth || width < minWidth || height > maxHeight || height < minHeight) && isLockRatio) {
      sizecorrect();
      return false;
    } else {
      sizecorrect();
      return true;
    }
  };
  //if (clipStart.corner) {
  height = clipStart!.height + (clipStart!.corner > 1 && clipStart!.corner < 4 ? 1 : -1) * (clipStart!.y - clientY);
  //}
  switch (clipStart!.corner) {
    case 1:
      width = clipStart!.width - clipStart!.x + clientX;
      if (isLockRatio) {
        height = width / (clipWidth / clipHeight);
      }
      if (!sizeinspect()) {
        return undefined;
      }
      break;
    case 2:
      width = clipStart!.width - clipStart!.x + clientX;
      if (isLockRatio) {
        height = width / (clipWidth / clipHeight);
      }
      if (!sizeinspect()) {
        return undefined;
      } else {
        clipY = clipStart!.clipY - (height - clipStart!.height);
      }

      break;
    case 3:
      width = clipStart!.width + clipStart!.x - clientX;
      if (isLockRatio) {
        height = width / (clipWidth / clipHeight);
      }
      if (!sizeinspect()) {
        return undefined;
      } else {
        clipY = clipStart!.clipY - (height - clipStart!.height);
        clipX = clipStart!.clipX - (width - clipStart!.width);
      }

      break;
    case 4:
      width = clipStart!.width + clipStart!.x - clientX;
      if (isLockRatio) {
        height = width / (clipWidth / clipHeight);
      }
      if (!sizeinspect()) {
        return undefined;
      } else {
        clipX = clipStart!.clipX - (width - clipStart!.width);
      }
      break;
    default:
      break;
  }
  return { width, height, clipX, clipY };
}

/**
 * 单指拖动图片计算偏移
 */
export function imageTouchMoveOfCalcOffset(touchRelative: Data['touchRelative'], clientXForLeft: number, clientYForLeft: number) {
  return {
    left: clientXForLeft - touchRelative[0]!.x,
    top: clientYForLeft - touchRelative[0]!.y,
  };
}
